﻿# importing required modules
import os, time, py7zr, shutil, subprocess


class log_folder_dir:
    '类:生产log每日文件夹'

    path_7za = r'.\7z2201-extra\7za.exe'

    def __init__(self, root: str, relative_path: list[str], save_level: int):
        # C:\AA1 Result=root / BYD X1F=level 1/ 2023=level 2。。。
        # C:\AA1 Result\BYD X1F\2023\08\11
        dash = '_'
        slash = '\\'
        self.new_name = dash.join(relative_path)
        self.path = root + slash + slash.join(relative_path)
        self.target_path = root + slash + slash.join(relative_path[:save_level])
        self.m_time = os.stat(self.path).st_mtime

    def clean_sweep(self, time_limit) -> bool:
        mark = '-cleaned'
        cleaned = 0
        current_time = int(time.time())
        # C:\AA1 Result\BYD X1F\2023\08\11=>Root path(day)
        # Root/part folder => Part path
        # Part path/file_in_part => file_in_part_path
        for part_folder in os.listdir(self.path):
            part_path = os.path.join(self.path, part_folder)
            if part_folder[-len(mark) :] == mark or os.path.isfile(part_path):
                continue
            part_time = int(os.stat(part_path).st_mtime)
            if current_time - part_time < time_limit:
                continue
            for file_in_part in os.listdir(part_path):
                file_in_part_path = os.path.join(part_path, file_in_part)
                if file_in_part[:5] == 'Sweep' and os.path.isdir(file_in_part_path):
                    shutil.rmtree(file_in_part_path)
            os.rename(part_path, part_path + mark)
            cleaned += 1
        return cleaned

    def sevenzip(self, remian_time: int, methord=4) -> int:
        now = time.time()
        if (now - self.m_time) > remian_time:
            timemark = "-" + time.strftime("%y%m%d%H%M%S", time.localtime(now))
            newpath_newname = self.target_path + "\\" + self.new_name + timemark + ".7z"
            path_7za = "\"" + self.path_7za + "\""
            newP_N = "\"" + newpath_newname + "\""
            oldP_N = "\"" + self.path + "\""
            sw = " a -bso2 -bse2 -bsp2 -mmt2 "
            cmd = path_7za + sw + newP_N + " " + oldP_N
            match methord:
                case 1:
                    with py7zr.SevenZipFile(newpath_newname, 'w') as archive:
                        archive.writeall(self.path, arcname=self.new_name)
                    return 0
                case 2:
                    os.system("cmd /c \"" + cmd + "\"")
                    return 0
                case 3:
                    subprocess.call(cmd)
                    return 0
                case 4:
                    ret = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
                    for line in iter(ret.stdout.readline, 'b'):
                        line = line.rstrip().decode('utf8')
                        if subprocess.Popen.poll(ret) is not None:
                            if line == "":
                                break
                    ret.stdout.close()
                    if ret.returncode == 0:
                        print(newpath_newname + " archived!\n")
                        # delete zipped file
                        shutil.rmtree(self.path)
                        return 0
                    else:
                        print(self.path + " archived with some error")
                        return 2
        else:
            return 1


class log_folder_dirs:
    def __init__(self, root_dir: str, list_level=4, save_level=2):
        self.list_level = list_level
        self.save_level = save_level
        if self.list_level < self.save_level:
            print("Error:Parameter intut with issue, required:list_level>=save_level")
            return
        self.root_dir = root_dir
        self.part_folder_list = self.get_all_folder(self)

    def get_all_folder(
        self, working_dir="", rel_path: list[str] = [], i=1
    ) -> list[log_folder_dir]:
        empty_lis: list[str] = []
        if i > self.list_level:
            return empty_lis
        folder_lis: list[log_folder_dir] = []
        if i == 1:
            folders = os.listdir(self.root_dir)
            working_dir = self.root_dir
        else:
            folders = os.listdir(working_dir)
        for folder in folders:
            re_path_add = rel_path + [folder]
            root_add_folder = os.path.join(working_dir, folder)
            if os.path.isfile(root_add_folder):
                continue
            if i < self.list_level:
                folder_lis = folder_lis + self.get_all_folder(
                    root_add_folder, re_path_add, i + 1
                )
            else:
                fol2add = log_folder_dir(self.root_dir, re_path_add, self.save_level)
                folder_lis.append(fol2add)
        return folder_lis

    def clean_sweeps(self, remain_time):
        cleaned = 0
        for folder in self.part_folder_list:
            cleaned = cleaned + folder.clean_sweep(remain_time)
        return cleaned

    def sevenzips(self, remain_time, zips_in_one_time=5) -> int:
        count = 0
        for folder in self.part_folder_list:
            if count > zips_in_one_time - 1:
                break
            match folder.sevenzip(remain_time, 4):
                case 0:
                    count += 1
                case 1:
                    pass
                case 2:
                    count = -1
                    break
        return count


def main(log_root_dir, sweep_remain, logs_Remain, zips_in_one_time: int = 5):
    if zips_in_one_time < 0:
        print("Error:'zips_in_one_time'<0,Please Reset")
        return
    # Get the list folder
    folder_lists = log_folder_dirs(log_root_dir, 4, 2)
    # Clean Sweep folder
    cleaned = folder_lists.clean_sweeps(sweep_remain)
    if cleaned > 0:
        print(
            "Cleaned %s parts folder with Sweep remain for more then %.2f mins"
            % (cleaned, (sweep_remain / 60))
        )
    else:
        print("No sweep folder to delete")
    zipped = folder_lists.sevenzips(logs_Remain, zips_in_one_time)
    match zipped:
        case -1:
            print("Error occured,archice process stopped")
        case 0:
            if zips_in_one_time == 0:
                print("zips_in_one_time = 0,No zip task!")
            else:
                print("No file ready to archive!")
        case _:
            print("%s files archived successfully!" % zipped)


if __name__ == "__main__":
    log_root_dir = r'C:\Users\tding1\Desktop\123'
    main(log_root_dir, 18, 36)
